package com.trinh.utils.crypto.cryptors;


import com.trinh.utils.crypto.config.KeyConfig;
import com.trinh.utils.crypto.enu.Algorithm;
import com.trinh.utils.crypto.enu.CharFormater;
import com.trinh.utils.crypto.enu.Padding;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Security;
import java.util.Base64;

/**
 * @Author: TrinhRae
 * @Package: com.trinh.utils.crypto
 * @Project: generaltools
 * @Date: 2025/6/23 8:37
 */
public class SM4Util {
    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    private KeyConfig keyConfig;
    private Algorithm algorithm;
    private Padding padding;
    private CharFormater keyCharFormater;

    public SM4Util(KeyConfig keyConfig) {
        this.keyConfig = keyConfig;
        this.algorithm = Algorithm.AES_CBC;
        this.padding = Padding.PKCS5;
        this.keyCharFormater = CharFormater.UTF_8;
    }

    public SM4Util(KeyConfig keyConfig, Algorithm algorithm, Padding padding, CharFormater keyCharFormater) {
        this.keyConfig = keyConfig;
        this.algorithm = algorithm;
        this.padding = padding;
        this.keyCharFormater = keyCharFormater;
    }

    /**
     * 加密
     *
     * @param content 明文内容
     * @return 加密后的Base64字符串
     */

    public String encrypt(String content) throws Exception {
        Cipher cipher = cipherBuilder(Cipher.ENCRYPT_MODE);
        byte[] encrypted = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }

    /**
     * 解密
     *
     * @param encrypted 加密后的Base64字符串
     * @return 明文字符串
     */

    public String decrypt(String encrypted) throws Exception {
        Cipher cipher = cipherBuilder(Cipher.DECRYPT_MODE);
        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encrypted));
        return new String(decrypted, StandardCharsets.UTF_8);
    }

    /**
     * 密码构建器
     *
     * @return
     * @throws Exception
     */
    public Cipher cipherBuilder(int mode) throws Exception {
        Cipher cipher = Cipher.getInstance(algorithm.getTransformation(padding), "BC");
        SecretKeySpec keySpec = new SecretKeySpec(keyCharFormater.getTool().toBytes(keyConfig.getSecretKey()), "SM4");
        if (algorithm.isNeedIv()) {
            if (keyConfig.getIv() == null) {
                throw new IllegalArgumentException("当前加密算法" + algorithm.getMode() + "需要传入IV");
            }
            IvParameterSpec ivSpec = new IvParameterSpec(keyCharFormater.getTool().toBytes(keyConfig.getIv()));
            cipher.init(mode, keySpec, ivSpec);
        } else {
            cipher.init(mode, keySpec);
        }
        return cipher;
    }

}
